# 题目: 260. 只出现一次的数字 III

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

进阶:你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?

# 示例1:

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。

# 示例2:

输入:nums = [-1,0]
输出:[-1,0]

# 题解1: 哈希

我们可以进行一次遍历,并使用哈希将元素出现的次数记录下来,最后在遍历哈希找到只出现过一次的元素。

# 代码

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var singleNumber = function(nums) {
    let map = new Map()
    let res = []
    for(let i of nums){
        map.set(i,(map.get(i) || 0) + 1)
    }
    for(let [key,value] of map){
        if(value === 1)  res.push(key)
    }
    return res
};

# 题解2: 位运算

根据异或运算,相同为0,不同为1,我们可以将所有的元素进行异或,则可以得到:

x_1,x_2为数组中不同的两个元素。

下一步的我们需要从得到x拿到x_1,x_2。

借助 $x \oplus -x $ 取出 x 二进制表达式中最低位的那个1,设其为第l位,那么x_1和x_2在第l位一定一个是1,一个是0。

我们通过这一位将nums中的元素,分为两类,即一类是第l位为1,一类第l位为0。而x_1,x_2肯定在不同类的,而其余重复的两个元素一定会被分到同一类中。这样,我们就将nums分成了两个数组,每个数组包含了一个不重复的元素,在这个数组中,我们再次异或就可以得到答案。

# 代码

var singleNumber = function(nums) {
    let xorsum = 0;
    
    for (const num of nums) {
        xorsum ^= num;
    }
    let type1 = 0, type2 = 0;
    const lsb = xorsum & (-xorsum);
    for (const num of nums) {
        // 分类的同时,进行异或
        if (num & lsb) {
            type1 ^= num;
        } else {
            type2 ^= num;
        }
    }
    return [type1, type2];
};

# 参考资料